namespace OasisCiq.Xal
{
    // TODO: GeoRSS
    // TODO: XLink attributes

    using System.Collections.Specialized;
    using System.Xml;
    using System.Xml.Schema;
    using System.Xml.Serialization;
    using CommonTypes;
    using External;
    using Xml;
    using XS;

    /// <summary>
    /// Complex type that defines the structure of an address with geocode details for reuse
    /// </summary>
    public class AddressType : 
        IDataQualityGroup, 
        IValidityDateGroup, 
        ILanguageCodeGroup, 
        IXLink, 
        IExtendedAttributes, 
        IXmlSerializable
    {
        private static readonly XmlQualifiedName XmlElementName =
            new XmlQualifiedName("Address", XmlNamespaces.Address);

        public virtual FreeTextAddress FreeTextAddress { get; set; }

        /// <summary>
        /// Country details
        /// </summary>
        public virtual CountryType Country { get; set; }

        public virtual AdministrativeArea AdministrativeArea { get; set; }

        public virtual Locality Locality { get; set; }

        public virtual Thoroughfare Thoroughfare { get; set; }

        public virtual Premises Premises { get; set; }

        public virtual PostCode PostCode { get; set; }

        public virtual RuralDelivery RuralDelivery { get; set; }

        public virtual PostalDeliveryPoint PostalDeliveryPoint { get; set; }

        public virtual PostOffice PostOffice { get; set; }

        public virtual IGeoRss GeoRss { get; set; }

        public virtual LocationByCoordinates LocationByCoordinates { get; set; }

        /// <summary>
        /// Defines the type of address. An address type can be Primary Address,
        /// Secondary Address, Rural Address, Military Address, etc.
        /// </summary>
        public virtual AddressTypeList Type { get; set; }

        /// <summary>
        /// A unique address identifier such as postal delivery idetifier
        /// assigned to the address by local postal authority, e.g. DPID in Australia.
        /// </summary>
        public virtual CTString AddressId { get; set; }

        /// <summary>
        /// Type of address ID used. e.g. DPID, etc
        /// </summary>
        public virtual AddressIdTypeList AddressIdType { get; set; }

        /// <summary>
        /// A globally unique identifier assigned to the address
        /// </summary>
        public virtual CTString Id { get; set; }

        /// <summary>
        /// The purpose the address is used for. E.g. Postal, residential,
        /// business, exchange, update, create, delete, etc
        /// </summary>
        public virtual AddressUsageList Usage { get; set; }

        /// <summary>
        /// Mode of delivery of address. For example:
        /// rural route, normal delivery, post office box, etc.
        /// </summary>
        public virtual DeliveryModeList DeliveryMode { get; set; }

        /// <summary>
        /// Status of the entity. e.g. Old, Current, Inactive, Active, etc
        /// </summary>
        public virtual StatusList Status { get; set; }

        public virtual XSDateTime DateValidFrom { get; set; }

        public virtual XSDateTime DateValidTo { get; set; }

        /// <summary>
        /// A primary key to reference Address.
        /// </summary>
        public virtual CTString AddressKey { get; set; }

        /// <summary>
        /// A foreign key to reference attribute Key of Address.
        /// </summary>
        public virtual CTString AddressKeyRef { get; set; }

        public virtual DataQualityTypeList DataQualityType { get; set; }

        public virtual XSDateTime ValidFrom { get; set; }

        public virtual XSDateTime ValidTo { get; set; }

        public virtual XSLanguage LanguageCode { get; set; }

        public virtual NameValueCollection ExtendedAttributes { get; set; }

        #region IXmlSerializable implementation

        XmlSchema IXmlSerializable.GetSchema()
        {
            return null;
        }

        public virtual void ReadXml(XmlReader reader)
        {
            var wrapper = XmlUtilities.Wrap(reader);
            if (XmlUtilities.MoveToElement(wrapper, XmlElementName))
            {
                new XalXmlReader(wrapper).ReadAddress(
                    this, 
                    XmlElementName.Name, 
                    XmlElementName.Namespace);
            }
        }

        public virtual void WriteXml(XmlWriter writer)
        {
            new XalXmlWriter(writer).WriteAddress(this);
        }

        #endregion
    }
}